package cn.uestc.labhms.modules.hms.util;

import cn.uestc.labhms.modules.hms.dao.HmsChiEngDao;
import cn.uestc.labhms.modules.hms.dao.HmsUserPermDao;
import cn.uestc.labhms.modules.hms.dao.XlsxDao;
import cn.uestc.labhms.modules.hms.entity.HmsChiEngEntity;
import cn.uestc.labhms.modules.hms.entity.HmsUserPermEntity;
import cn.uestc.labhms.modules.hms.exception.HMSException;
import cn.uestc.labhms.modules.sys.entity.SysUserEntity;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import javafx.scene.control.Tab;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.*;

/**
 * @author Mu.tz
 */
@Component
@Slf4j
public class TableUtil {
    private static HmsChiEngDao hmsChiEngDao;
    private static XlsxDao xlsxDao;
    private static HmsUserPermDao userPermDao;
    @Autowired
    public TableUtil(HmsChiEngDao hmsChiEngDao, XlsxDao xlsxDao, HmsUserPermDao userPermDao) {
        TableUtil.hmsChiEngDao = hmsChiEngDao;
        TableUtil.xlsxDao = xlsxDao;
        TableUtil.userPermDao = userPermDao;
    }

    /**
     * 获取所有符合条件的表名, 同时去除无权限的表名
     * @return 英文表名
     */
    public static List<String> getValidTableNames(List<String> keysE) {
        // 获取数据库中所有的表名
        List<String> allTableNames = hmsChiEngDao.getTableNamesEN();
        // 获取所有同时拥有全部查询条件的表名
        List<String> tableNames = new LinkedList<>();
        for (String tableName : allTableNames) {
            QueryWrapper<HmsChiEngEntity> tableNameQuery = new QueryWrapper<>();
            tableNameQuery.eq("table_name_eng", tableName);
            List<HmsChiEngEntity> hmsChiEngEntities = hmsChiEngDao.selectList(tableNameQuery);
            if (ObjectUtils.isEmpty(hmsChiEngEntities)) {
                continue;
            }
            Set<String> filedESet = new HashSet<>();
            for (HmsChiEngEntity hmsChiEngEntity : hmsChiEngEntities) {
                filedESet.add(hmsChiEngEntity.getEngField());
            }
            if (filedESet.containsAll(keysE)) {
                tableNames.add(tableName);
            }
        }
        // 去除无权限的表名
        SysUserEntity principal = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
        int userId = principal.getUserId().intValue();
        List<HmsUserPermEntity> userPermEntities = userPermDao.selectList(
                new QueryWrapper<HmsUserPermEntity>()
                        .eq("user_id", userId)
                        .and(wrapper -> wrapper
                        .likeLeft("permission", "list")
                                .or()
                                .like("permission", "*"))
                        );
        Set<String> hasPermTableNames = new HashSet<>();
        userPermEntities.forEach(userPermEntity -> {
            String[] tmp = userPermEntity.getPermission().split(":");
            if (tmp.length > 2) {
                hasPermTableNames.add(tmp[1]);
            }
        });
        if (hasPermTableNames.contains("*")) {
            return tableNames;
        }
        tableNames.retainAll(hasPermTableNames);
        log.info("合法的查询表：{}", tableNames.toString());
        return tableNames;
    }

    /**
     * 使用key，val列表构建Map
     * @param keys
     * @param vals
     * @return
     */
    public static Map<String, String> parseData(List<String> keys, List<String> vals) {
        Map<String, String> map = new HashMap<>();
        for (int i = 0; i < keys.size(); i++) {
            map.put(keys.get(i), vals.get(i));
        }
        return map;
    }

    /**
     * 将map中英文key转为中文key
     * @param map
     * @param tableName 英文表名
     * @return
     */
    // TODO: 2021/11/11 代码可以优化，有时间优化，将List<Map>传进来，使用哈希表将字段映射存储起来，减少数据库I/O时间开销
    public static Map<String, String> convertKeyMap(Map<String, String> map, String tableName) {
        Map<String, String> res = new LinkedHashMap<>(map.size());
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String fieldC = hmsChiEngDao.getFieldE2C(tableName, entry.getKey());
            if (ObjectUtils.isEmpty(fieldC)) {
                throw new HMSException("更改表结构时未添加相应的中文名引发的连锁反应，请联系数据库管理员处理此问题");
            }
            res.put(fieldC, entry.getValue());
        }
        return res;
    }

    /**
     * 将map中中文key转为英文key
     * @param map
     * @param tableNameE 英文表名
     * @return
     */
    public static Map<String, String> convertKeyMap2E(Map<String, String> map, String tableNameE) {
        Map<String, String> res = new HashMap<>();
        String tableNameC = hmsChiEngDao.getTableNameE2C(tableNameE);
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String fieldE = hmsChiEngDao.getFieldC2E(tableNameC, entry.getKey());
            if (fieldE == null) {
                throw new HMSException("数据库中无该字段，请管理员查看数据库");
            }
            res.put(fieldE, entry.getValue());
        }
        return res;
    }

    /**
     * 返回单表分页数据
     * @param tableName 英文表名
     * @param map 字段-值对
     * @param curPage 当前所在页
     * @param pageSize 每页容量
     * @return 单表分页数据
     */
    public static HMSPageUtils getTableData(String tableName, Map<String, String> map, int curPage, int pageSize) {
        int curIndex = (curPage - 1) * pageSize;
        List<LinkedHashMap<String, String>> maps = xlsxDao.conditionsFind(tableName, map, pageSize, curIndex);
        List<Map<String, String>> resC = new LinkedList<>();
        log.info("当前查询出符合条件的记录为：{}", maps);
        // 将查询出的英文字段转为中文字段，用于前端渲染
        for (Map<String, String> tmpMap : maps) {
            resC.add(TableUtil.convertKeyMap(tmpMap, tableName));
        }
        HmsChiEngEntity hmsChiEngEntity = hmsChiEngDao.selectOne(new QueryWrapper<HmsChiEngEntity>().eq("table_name_eng", tableName).last("limit 1"));
        return new HMSPageUtils(resC, resC.size(), pageSize, curPage, hmsChiEngEntity.getTableNameChi());
    }
}
